package ncc.bs.Plugins;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.InputStream;
import java.nio.charset.StandardCharsets;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Base64;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.UUID;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.sm.misc.BASE64Encoder;
import com.yl.request.common.glaencrypt.enums.CryptLevel;
import com.yl.request.common.glaencrypt.enums.NetworkType;
import com.yl.request.common.glaencrypt.DxpCrypt;
import cn.hutool.core.io.IoUtil;
import nc.bs.logging.Log;
import nc.bs.pub.pa.PreAlertObject;
import nc.bs.pub.taskcenter.BgWorkingContext;
import nc.bs.pub.taskcenter.IBackgroundWorkPlugin;
import nc.vo.pub.BusinessException;
import nc.vo.pub.lang.UFDate;

/**
 * 后台任务抽象类
 *
 * @author Administrators
 * @date k2024年2月19日
 */
public abstract class AbstractBackgroundWorkPlugin implements IBackgroundWorkPlugin {
	private static final Log log = null;

	private final int count = 10; // 一次性同步的条数
	private final String QH = "350200000"; // 区划

	/**
	 * 区划:350200 单位:  401028，帐套:  0004 -- 提示错误
	 * 区划:350200 单位:  0004，    帐套: 401028 -- 提示错误
	 */
	private final String UNIT = "401028"; //  医院单位
	private final String ACCOUNT = "0005"; // 医院帐套401028  --测试：0005 正式:0004
	private final String ACCT_SET_NAME = "厦门大学附属心血管病医院";
	private final String AGENCY_NAME = "厦门大学附属心血管病医院";
	private final SimpleDateFormat ymd = new SimpleDateFormat("yyyyMMdd");
	private final SimpleDateFormat strtdate = new SimpleDateFormat("yyyy-MM-dd");
	private final SimpleDateFormat ymdsfm = new SimpleDateFormat("yyyyMMddHHmmss");
	private final SimpleDateFormat strtdtime = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
	// 财政公钥
	private static final String PUB_KEY = "MIIBMzCB7AYHKoZIzj0CATCB4AIBATAsBgcqhkjOPQEBAiEA/////v////////////////////8AAAAA//////////8wRAQg/////v////////////////////8AAAAA//////////wEICjp+p6dn140TVqeS89lCafzl4n1FauPkt28vUFNlA6TBEEEMsSuLB8ZgRlfmQRGajnJlI/jC7/yZgvhcVpFiTNMdMe8Nzai9PZ3nFm9zuNraSFT0KmHfMYqR0AC3zLlITnwoAIhAP////7///////////////9yA99rIcYFK1O79Ak51UEjAgEBA0IABHSZL6sf3I+vkh4lXDGkgu8UwD0Gcu5QMj2HJA6mzfU+DkgJ6DV6n+XtNJ+ZRL6ooH/NpHzOtc6CcS4gLof2vy8=";
	// 财政密钥
	private static final String PRIVATE_KEY =  "MIIBUQIBAQQg2EJXgrXjC6iwwCCW5qbR9kwVcp6Gd164ElDPKyipiO2ggeMwgeAC" +
			"AQEwLAYHKoZIzj0BAQIhAP7/AAAAAP//" +
			"MEQEIP7/AAAAAP/8BCAo6fqenZ9eNE1a" +
			"nkvPZQmn85eJ9RWrj5LdvL1BTZQOkwRBBDLEriwfGYEZX5kERmo5yZSP4wu/8mYL" +
			"4XFaRYkzTHTHvDc2ovT2d5xZvc7ja2khU9Cph3zGKkdAAt8y5SE58KACIQD+" +
			"cgPfayHGBStTu/QJOdVBIwIBAaFEA0IABOJVD/jik5D5XVCQ" +
			"+2tX23HR74N4URgoRtSa9gx0/kV9rasQA7XrQQ9Y543MfFDdblvJRKqajnmpmgf+" +
			"1smw60E=";

	@Override
	public PreAlertObject executeTask(BgWorkingContext context) throws BusinessException {
		try {
			getLog().info("----begin后台任务抽象类BackgroundWorkPlugin:【" + new UFDate() + "】-----");
			doBusiness(context.getKeyMap());
		} catch (Exception e) {
			getLog().error("后台任务异常:" + e.getMessage());
		}
		getLog().info("----end后台任务抽象类BackgroundWorkPlugin-----");
		return null;
	}

	/**
	 * 后台任务统一进入入口
	 *
	 * @param keyMap 前台配置配置参数信息 key=value,key=value
	 * @throws BusinessException
	 */
	@SuppressWarnings("rawtypes")
	public abstract void doBusiness(Map keyMap) throws BusinessException;

	/**
	 * 获取分组后的数据
	 *
	 * @return
	 * @throws BusinessException
	 */
	public List<List<Map<String, Object>>> getGroupAfterData(List<Map<String, Object>> lists) throws BusinessException {
		List<List<Map<String, Object>>> listparams = new ArrayList<List<Map<String, Object>>>();
		if (lists == null)
			return null;
		int wcount = lists.size() / count + 1; // 最外层需要循环次数
		for (int i = 1; i <= wcount; i++) {// 将数据进行分组
			List<Map<String, Object>> pjlist = new ArrayList<Map<String, Object>>();
			if (i < wcount) {
				for (int j = count * (i - 1); j < count * i; j++) {
					Map<String, Object> map = lists.get(j);
					if(map != null || map.get("acccode") == null &&  !map.get("acccode").toString().endsWith("科目合计") && !map.get("acccode").toString().endsWith("累计") && !map.get("acccode").toString().endsWith("总计")) {
						pjlist.add(map);
					}
				}
			} else {
				for (int j = count * (i - 1); j < lists.size(); j++) {
					Map<String, Object> map = lists.get(j);
					if(map != null || map.get("acccode") == null && !map.get("acccode").toString().endsWith("科目合计") && !map.get("acccode").toString().endsWith("累计") && !map.get("acccode").toString().endsWith("总计")) {
						pjlist.add(map);
					}
				}
			}
			listparams.add(pjlist);
		}
		return listparams;
	}

	/**
	 * 请求参数处理
	 *
	 * @param data  请求data参数
	 * @param sysid 业务标识
	 * @param appid 应用账号 BS_年度_区划编码_单位编码
	 * @return
	 * @throws Exception
	 */
	public String getParam(JSONArray data, String sysid, String appid) throws Exception {
		if (data == null || data.isEmpty())
			return null;
		JSONObject json = new JSONObject();
		String datas = handlerDataEncodeBase64(data);
		json.put("sysid", sysid); // 业务标识
		json.put("appid", appid); // 应用账号 调用方应用帐号ID，格式为： BS_年度_区划编码_单位编码
		json.put("noise", UUID.randomUUID());
		json.put("version", "1.0");
		json.put("secret", "1");
		json.put("data", datas);
		getLog().info("----第一步请求参数中的data:" + data);
		return getSign(json);
	}
	/**
	 *
	 * @param data 需要编码的数据
	 * @return Base64编码后的结果
	 * @throws Exception
	 */
	public String handlerDataEncodeBase64(JSONArray data) throws Exception {
		String resultdata = Base64.getEncoder().encodeToString(data.toString().getBytes(StandardCharsets.UTF_8));
		return resultdata;
	}

	/**
	 *
	 * @param json 需要进行加密的数据
	 * @return
	 * @throws Exception
	 */
	@SuppressWarnings("unchecked")
	public String getSign(JSONObject json) throws Exception {
		String sign = "";
		Map<String, Object> map = JSON.parseObject(json.toString(), Map.class);
		String str = "sysid=" + map.get("sysid") +
				"&appid=" + map.get("appid") +
				"&data=" + map.get("data") +
				"&noise=" + map.get("noise") +
				"&key=" + PUB_KEY +
				"&version=1.0";
		byte[] encrypt = encrypt(str, PUB_KEY, 1);
		String s1 = encodeBase64(encrypt);
		sign = String.format("{\"sign\":\"%s\"}", s1.replaceAll("[\r\n]", ""));
		getLog().info("----第二步请求参数中的sign");
		return sign;
	}

	public byte[] encrypt(String str, String publicKey, int cryptLevel) throws Exception {
		InputStream inputStream = null;
		try {
			inputStream = DxpCrypt.encryptInputStreamWapper(
					new ByteArrayInputStream(str.getBytes(StandardCharsets.UTF_8)), str.length(),
					getCryptLevel(cryptLevel), NetworkType.INTERNET, "01", publicKey);
			return IoUtil.readBytes(inputStream);
		} catch (Exception e) {
			throw new Exception(e);
		} finally {
			if (inputStream != null)
				inputStream.close();
		}
	}

	public static String encodeBase64(byte[] bytes) {
		BASE64Encoder encoder = new BASE64Encoder();
		return encoder.encodeBuffer(bytes);
	}

	public static byte[] inputToByte(InputStream inputStream) throws Exception {
		ByteArrayOutputStream output = new ByteArrayOutputStream();
		try {
			int bytesRead;
			byte[] buffer = new byte[4096];
			while ((bytesRead = inputStream.read()) != -1) {
				output.write(buffer, 0, bytesRead);
			}
			return output.toByteArray();
		} catch (Exception e) {
			throw new Exception(e);
		} finally {
			if (output != null)
				output.close();
		}
	}

	public static CryptLevel getCryptLevel(int level) {
		switch (level) {
			case 0:
				return CryptLevel.PUBLIC;
			case 1:
				return CryptLevel.DEFAULT;
			case 2:
				return CryptLevel.PROTECTED;
			case 3:
				return CryptLevel.PRIVATE;
			default:
				throw new RuntimeException();
		}
	}
	/**
	 * 获取区划与单位
	 * @return
	 */
	public String getAppid() {
		String[] dates = ymd.format(new Date()).split("-");
		return "BS"+"_"+dates[0]+"_"+QH+"_"+UNIT;
	}

	/**
	 * 获取财政区划
	 * @return
	 */
	public String getMOF_DIV_CODE() {
		return QH;
	}

	public String getACCT_SET_NAME() {
		return ACCT_SET_NAME;
	}

	public String getAGENCY_NAME() {
		return AGENCY_NAME;
	}

	/**
	 * 医院单位
	 * @return
	 */
	public String getUnit() {
		return UNIT;
	}

	/**
	 * 帐套
	 * @return
	 */
	public String getAccount() {
		return ACCOUNT;
	}

	/**
	 * 获取当前日期 年月日
	 * @param date  yyyy-mm-dd HH:MM:SS
	 * @return  yyyymmdd
	 * @throws Exception
	 */
	public String getYMD(Object date) throws Exception{
		if(date == null ) return "";
		String format = ymd.format(strtdate.parse(date.toString()));
		return format;
	}

	/**
	 * 获取当前日期 年月日时分秒
	 * @param date  yyyy-mm-dd HH:MM:SS
	 * @return  yyyyMMddHHmmss
	 * @throws Exception
	 */
	public String getYMDHMS(Object date) throws Exception{
		String format = "";
		if(date == null ) {
			format = ymdsfm.format(new Date());
		}else {
			format = ymdsfm.format(strtdtime.parse(date.toString()));
		}
		return format;
	}
	/**
	 * 日志文件记录
	 * @return
	 */
	public static Log getLog() {
		return log == null ? Log.getInstance("czlog") : log;
	}

}
